Search menu

Trying to make a user menu so users can enter their specifc terms in a dialogue box and have it search through the file.

I am trying a loop that can parse a the string separated by commas into an array or another string. Then the loop needs to run through each term.

Below is my code. Commented out in green is some pseudo code that I am not sure what to do next.

Any guidance would be much appreciated.
 

pragma encoding, "UTF-8"
 
DB searchDB = create ("Search Utility", styleStandard)
DBE InfoTextDBE = text(searchDB, "Instructions", "Enter Search terms. Enter attribute name for column.", 200, 50, true)
DBE SearchTextDBE = text(searchDB, "Search terms", "", 200, 50, false)
Module m = current 
Object o = current
 
    
void searchFunction (DB win) 
        {
                Buffer bufResults = create()
                string objectHeading, objectText, objectBoth
                string searchTerms[] = get SearchTextDBE
                
               /**
                //for the entire string entered in the text box 
                for (i=0; i<sizeof(searchTerms); i++) 
                {
                   parse out each term separated by a comma 
                   save each term into an array 
                   bufResults += Terms[i]
                   then continue until the end of string
                }
                **/
 
                for o in m do
                {
                        //search both object text and headings
                        objectText = richText o."Object Text"
                        objectHeading = richText o."Object Heading" 
                        objectBoth = objectHeading " " objectText 
        
                        int offset = null
                        int length = null
                        bool matchCase = false
                        bool reverse = false
                        string Comma  
                        Comma = ", "
                        bufResults = ""
  
                        //loop through all terms in the array
                        for (i=0; i<sizeof(searchTerms); i++)
                        {
                         //Search all objects.
                         if (findPlainText (objectBoth, searchTerms[i], offset, length, matchCase, reverse))
                                {
                                bufResults += searchTerms[i]
                                bufResults += Comma
                                bufResults += "\n"
                                o."SearchTerm" = stringOf(bufResults)    //set the attribute to the term(s) found.
                        
                                continue // Search remaining terms
                                }
                                else
                                {
                                        null
                                }
                  }
                }
        }    
 
void closeWindow (DB searchDB) 
{
hide (searchDB)
}
apply (searchDB, "Search Terms", searchFunction)
close (searchDB, true, closeWindow)
show searchDB
}

SystemAdmin - Fri Feb 01 13:16:47 EST 2013

Re: Search menu
llandale - Fri Feb 01 14:12:51 EST 2013

I write code inside out; write the guts that does the work then add the loops and functions to support the guts.

[1] Your guts should look like this:

setEmpty(bufResults)
for (i=0; i<sizeof(searchTerms); i++)
{
   if (findPlainText (objectBoth, searchTerms[i], offset, length, matchCase, reverse))
   {  if (length(bufResults) > 0) then bufResults += Comma
      bufResults += searchTerms[i]
   }
}
o."SearchTerm" = tempStringOf(bufResults)    //set the

 

  • set the results at the end; even when no search terms were found
  • You don't need a comma AND an EOL
  • your "continue" at the bottom and also that null else clause look confusing to me.
  • I think I would use "matches" instead of "findPlainText".
  • I note term "shall" will match words "shallow" and "marshall". I think your terms are actually "words" in which case the "contains" command may help. I'll let other folks improve this weakness.


[2] I think this object loop is better:

 

 

for o in entire m do
{  if (isDeleted(o))    continue


This divorces your code from the current display set.

[3] "arrays" (your searchTerms) are awkward to manage since you MUST define their size when they are declared. Using a Skip list is better:

 

 

Skip skpTerms = createString()
for each Term specified by user
{  put(skpTerms, thisTerm, thisTerm)
}
..
    // now change your "guts" above:
for Term in skpTerms do
{  findPlainText bla bla bla
}
delete(skpTerms)


If nothing else, this will sort out duplicate "Terms" the user may have specified.

[4] Parsing. Seems to me there have been string parsing functions posted. Here is one so long as you use Delims of space, comma, EOL " ,\n". If your "terms" may have spaces in it then use delims of ",\n", but then strip the white space off start and end of your terms.

 

 

//*************************
string    fStripNextEntry(string &AttrVal, Delims)
{            // Strip the next valid "Entry" from  the Attribute Value;
                //      updating the remaining value.  "Entries" are separated by ANY of the
                // Characters in the Delim variable (such as "\n").  The start and end of the
                //      string are considered delimiters; thus a string with no Delims will return that string.
                // This is useful when parsing an attribute that contains valid link
                //      information, such as generated by "CaptureLinks.dxl" or "capture5.dxl".
                // The calling program is advised to ignore null returned Entries, but
                //      keep looping until the updated AttrVal is null. e.g.:
                //              AttrVal         = fGetAttrVal(obj, NameAttr)
                //              AttrValTemp     = AttrVal
                //              while (!null AttrValTemp)
                //              {  Entry     = fStripNextEntry(AttrValTemp, cl_Delims)
                //                 if (null Entry) continue
                //                 <Deal with valid 'Entry'>
                //              }
                // Note: user may want to set Delims to white space cl_White or cl_Delims.
 
        int     AttrValLength   = length(AttrVal)
        int     Offset, LenDelims       = length(Delims)
        int     iAttr, iDelim
        string  Entry, OutAttrVal
        
                        // Find the First Delim, ignore all others.
                        //      For each character in the AttrVal..
                        //         For each character in the Delims
                        //            Is Character same as Delim?
        Offset = -1
        for (iAttr=0; iAttr<AttrValLength; iAttr++)
        {  for (iDelim=0; iDelim<LenDelims; iDelim++)
           {  if (Offset == -1 and AttrVal[iAttr] == Delims[iDelim])
              {  Offset = iAttr
                 break
              }
           }
           if (Offset >= 0) break
        }    // end looking for the next Delim
 
        if (Offset < 0)
        {            // No Delims in AttrVal.  Return entire AttrVal
           Entry        = AttrVal
           OutAttrVal   = ""
        }    // end no delims found
        else
        {            // A Delim is Found
           if (Offset == 0)
                Entry   = ""          // a Delim at start of AttrVal
           else Entry   = AttrVal[0:Offset-1]
 
           if (AttrValLength == Offset+1)
                OutAttrVal      = ""          // the only Delim is at end of AttrVal
           else OutAttrVal      = AttrVal[Offset+1:]
        }    // end yes a delim found
        AttrVal = OutAttrVal    // DXL bug.  It seems modifying a call-parameter
                                        //   variable (AttrVal) in the middle of a function
                                        //   doesn't work.  So we stage the results (OutAttrVal)
                                        //   Instead.  Oh well.
        return(Entry)
}    // end fStripNextEntry()


I wrote that function 11 some years ago and perhaps I should do it more elegantly.

-Louie